import socket
import pyaudio
import sys
import time
import wave

# 音频参数
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 48000
DEFAULT_SERVER_IP = '192.168.25.181'


def get_valid_input_device(p):
    """获取有效的输入设备索引"""
    try:
        # 尝试获取默认输入设备
        default_input = p.get_default_input_device_info()
        if default_input['maxInputChannels'] > 0:
            print(f"使用默认输入设备: {default_input['name']}")
            return default_input['index']
    except Exception as e:
        print(f"无法获取默认输入设备: {str(e)}")

    # 扫描所有可用的输入设备
    print("扫描可用的输入设备...")
    input_devices = []
    for i in range(p.get_device_count()):
        try:
            dev = p.get_device_info_by_index(i)
            if dev['maxInputChannels'] > 0:
                input_devices.append(dev)
                print(f"找到输入设备 {i}: {dev['name']}")
        except:
            continue

    if not input_devices:
        print("错误：未找到任何输入设备！")
        return None

    # 使用第一个有效的输入设备
    device = input_devices[0]
    print(f"使用输入设备: {device['name']} (索引: {device['index']})")
    return device['index']


def mic_client(server_ip):
    print(f"尝试连接到服务器: {server_ip}")

    try:
        # 创建PyAudio实例
        p = pyaudio.PyAudio()
        print("PyAudio初始化成功")
    except Exception as e:
        print(f"PyAudio初始化失败: {str(e)}")
        return

    # 获取有效的输入设备
    input_device = get_valid_input_device(p)
    if input_device is None:
        print("错误：没有可用的输入设备")
        p.terminate()
        return

    while True:
        try:
            # 创建新socket连接
            client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            client_socket.settimeout(3)
            print(f"尝试连接到 {server_ip}:12345")
            client_socket.connect((server_ip, 12345))
            print(f"成功连接到服务器: {server_ip}")

            # 添加流控握手
            client_socket.settimeout(1.0)
            try:
                # 等待服务器准备信号
                ready_signal = client_socket.recv(11)
                if ready_signal == b"ServerReady":
                    print("收到服务器准备信号，开始传输")
                    flow_control_enabled = True
                else:
                    print("未收到有效准备信号，禁用流控")
                    flow_control_enabled = False
            except socket.timeout:
                print("等待准备信号超时，禁用流控")
                flow_control_enabled = False

            # 设置非阻塞模式
            client_socket.setblocking(False)

            # 初始化音频流
            print("初始化音频流...")
            stream = p.open(
                format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                input_device_index=input_device,  # 关键：指定输入设备
                frames_per_buffer=CHUNK,
                start=False  # 先不启动
            )

            # 启动音频流
            stream.start_stream()
            print("音频流已启动")

            # 初始化流控变量
            last_send_time = time.time()

            try:
                print("开始传输麦克风音频... (按Ctrl+C停止)")
                while True:
                    # 检查流是否活动
                    if not stream.is_active():
                        print("音频流已停止，尝试重启...")
                        stream.start_stream()
                        time.sleep(0.5)
                        continue

                    # 读取音频数据
                    try:
                        data = stream.read(CHUNK, exception_on_overflow=False)
                    except Exception as e:
                        print(f"读取音频数据时出错: {str(e)}")
                        time.sleep(0.1)
                        continue

                    # 添加流控机制
                    if flow_control_enabled:
                        current_time = time.time()
                        elapsed = current_time - last_send_time

                        # 确保时间差有效
                        if elapsed < 0:
                            # 时间异常，重置
                            last_send_time = current_time
                            elapsed = 0

                        # 控制发送速率 (约20包/秒)
                        if elapsed < 0.045:  # 22fps
                            sleep_time = 0.045 - elapsed
                            if sleep_time > 0:
                                time.sleep(sleep_time)

                        # 更新发送时间
                        last_send_time = time.time()

                    try:
                        # 尝试发送数据
                        client_socket.sendall(data)
                    except BlockingIOError:
                        # 发送缓冲区满，等待
                        if flow_control_enabled:
                            time.sleep(0.01)
                    except (BrokenPipeError, ConnectionResetError):
                        print("连接中断，尝试重连...")
                        break
                    except Exception as e:
                        print(f"发送数据时出错: {str(e)}")
                        break

            except KeyboardInterrupt:
                print("\n用户终止传输")
                break

            finally:
                print("清理资源...")
                if 'stream' in locals():
                    stream.stop_stream()
                    stream.close()
                client_socket.close()
                time.sleep(1)  # 重连前等待

        except (ConnectionRefusedError, socket.timeout, OSError) as e:
            print(f"连接错误: {e}, 5秒后重试...")
            time.sleep(5)

        except Exception as e:
            print(f"发生意外错误: {str(e)}, 5秒后重试...")
            time.sleep(5)

        except KeyboardInterrupt:
            print("\n程序终止")
            break

    print("释放资源...")
    p.terminate()
    print("所有资源已释放")


if __name__ == "__main__":
    # 灵活处理命令行参数
    server_ip = DEFAULT_SERVER_IP
    if len(sys.argv) == 2:
        server_ip = sys.argv[1]
    elif len(sys.argv) > 2:
        print("用法: python mic_client.py [服务器IP]")
        print(f"将使用默认服务器IP: {DEFAULT_SERVER_IP}")
    else:
        print(f"使用默认服务器IP: {DEFAULT_SERVER_IP}")

    # 添加调试信息
    print(f"Python版本: {sys.version}")
    print(f"PyAudio版本: {pyaudio.__version__}")

    mic_client(server_ip)